// This file is part of OpenMeca, an easy software to do mechanical simulation.
//
// Author(s)    :  - Damien ANDRE  <openmeca@gmail.com>
//
// Copyright (C) 2012 Damien ANDRE
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


#ifndef OpenMeca_Gui_WidgetInterface_hpp
#define OpenMeca_Gui_WidgetInterface_hpp


#include <cassert>

#include "OpenMeca/Gui/Widget.hpp"




namespace OpenMeca
{
  namespace Gui
  {


    template<class T>
    class WidgetInterface : public Widget
    {
      
    public:
      WidgetInterface(QWidget& parent);
      virtual ~WidgetInterface();
      virtual void SetValue(T&);
      void ApplyChangement();
      T& GetCopy();
      T& GetValue();
      T& GetInitialValue();
      void CancelChangement();
      void Reset();
      virtual void SetValue_CallBack(){}//Usefull to use widget... inside widget (see WidgetMatrix for example).
      
    protected:
      virtual void Init() = 0;
      

    private:
      T* val_;
      T* copy_;
      T* initialValue_;
    };

    template<class T>
    inline
    WidgetInterface<T>::WidgetInterface(QWidget& parent)
      :Widget(parent),
       val_(0),
       copy_(0),
       initialValue_(0)
    {
    }
    
    template<class T>
    inline
    WidgetInterface<T>::~WidgetInterface()
    {
    }

    template<class T>
    inline T&
    WidgetInterface<T>::GetValue()
    {
      assert(val_!=0);
      return *val_;
    }



    template<class T>
    inline void 
    WidgetInterface<T>::SetValue(T& val)
    {
      assert(val_==0);
      assert(copy_ == 0);
      assert(initialValue_ == 0);
      val_ = &val;
      copy_         = new T(val);
      initialValue_ = new T(val);
      SetValue_CallBack();
      Init();
    }


    template<class T>
    inline void     
    WidgetInterface<T>::CancelChangement()
    {
      GetValue() = GetInitialValue();
      GetCopy() = GetValue();
      Init();
    }

    template<class T>
    inline void     
    WidgetInterface<T>::ApplyChangement()
    {
      assert(Check()==true);
      GetValue() = GetCopy();
    }

    template<class T>
    inline void     
    WidgetInterface<T>::Reset()
    {
      delete copy_;
      delete initialValue_;
      val_          = 0;
      copy_         = 0;
      initialValue_ = 0;
    }


    template<class T>
    inline T&  
    WidgetInterface<T>::GetCopy()
    {
      assert(copy_ != 0);
      return *copy_;
    }

    
    template<class T>
    inline T&  
    WidgetInterface<T>::GetInitialValue()
    {
      assert(initialValue_ != 0);
      return *copy_;
    }


  }
}
#endif
